# 安装ImageWatch，并在代码中通过设置断点，观察处理中间结果图像。
# 使用光流估计方法，在前述测试视频上计算特征点，进一步进行特征点光流估计。
#光流估计基本思路：
#1.视频采集
#2.图像预处理
#3.提取特征点
#4.使用光流法估计特征点运动
#5.相邻帧及特征点交换
import cv2 as cv
import copy
videoFileName=r"D:\AI\第三周\vtest.avi"
#角点检测参数
feature_params=dict(
    maxCorners=100,
    qualityLevel=0.3,
    minDistance=7,
    blockSize=7
)
#lucas kanade光流法参数
lk_params=dict(winSize=(15,15),
               maxLevel=2,
               criteria=(cv.TERM_CRITERIA_EPS|cv.TERM_CRITERIA_COUNT,10,0.03))
cap=cv.VideoCapture(videoFileName)
#计算第一帧特征点
ret,prev=cap.read()
prevGray=cv.cvtColor(prev,cv.COLOR_BGR2GRAY)
p0=cv.goodFeaturesToTrack(prevGray,mask=None,**feature_params)
while True:
    ret,frame=cap.read()
    if not ret:
        break
    gray=cv.cvtColor(frame,cv.COLOR_BGR2GRAY)
    #计算光流
    p1,st,err=cv.calcOpticalFlowPyrLK(prevGray,gray,p0,None,**lk_params)
    #选取好的跟踪点
    goodPoints=p1[st==1]
    goodPrevPoints=p0[st==1]
    #在结果图像中跌加画出特征点和计算出来的光流向量
    res=frame.copy()
    drawColor=(0,0,255)
    drawColor1 = (0, 255, 0)
    for i,(cur,prev) in enumerate(zip(goodPoints,goodPrevPoints)):
        x0, y0 = cur.ravel()  # 得到这一帧特征点位置
        x1, y1 = prev.ravel()  # 得到上一帧特征点位置
        cv.line(res, (x0, y0), (x1, y1), drawColor)  # 把帧间这条线画出来
        cv.circle(res, (x0, y0), 3, drawColor1)  # 把这一帧特征点位置圈出来
    #更新上一帧
    prevGray=gray.copy()
    p0=goodPoints.reshape(-1,1,2)
    #显示计算结果图像
    cv.imshow('检测结果',res)
    key=cv.waitKey(30)#每一帧间隔30秒
    if key==27:
        break
